﻿using System;

namespace _1___Graph {
    public class InvalidGraphException : Exception {
        public InvalidGraphException(string message) : base(message) { }
    }
    public interface Graph {
        public double this[int index] { get; set; }
        public double Area { get; }
        public bool IsValid();
    }

    public class Triangle : Graph {
        protected double sideA;
        protected double sideB;
        protected double sideC;

        public Triangle(double sideA, double sideB, double sideC) {
            this.sideA = sideA;
            this.sideB = sideB;
            this.sideC = sideC;
        }

        public double this[int index] {
            get {
                switch (index) {
                    case 0:
                        return sideA;
                    case 1:
                        return sideB;
                    case 2:
                        return sideC;
                    default:
                        throw new IndexOutOfRangeException("Index was outside the bounds of the edge array.");
                }
            }
            set {
                switch (index) {
                    case 0:
                        sideA = value;
                        break;
                    case 1:
                        sideB = value;
                        break;
                    case 2:
                        sideC = value;
                        break;
                    default:
                        throw new IndexOutOfRangeException("Index was outside the bounds of the edge array.");
                }
            }
        }
        public double Area {
            get {
                if (IsValid()) {
                    return System.Math.Sqrt((sideA + sideB + sideC) * (sideA + sideB - sideC) * (sideA + sideC - sideB) * (sideB + sideC - sideA)) / 4;
                }
                throw new InvalidGraphException("Graph is invalid.");
            }
        }

        public bool IsValid() {
            return (sideA + sideB > sideC) && (sideA + sideC > sideB) && (sideB + sideC > sideA);
        }
    }

    public class Rectangle : Graph {
        protected double width;
        protected double height;
        public Rectangle(double width, double height) {
            this.width = width;
            this.height = height;
        }

        virtual public double this[int index] {
            get {
                switch (index) {
                    case 0:
                        return width;
                    case 1:
                        return height;
                    default:
                        throw new IndexOutOfRangeException("Index was outside the bounds of the edge array.");
                }
            }
            set {
                switch (index) {
                    case 0:
                        width = value;
                        break;
                    case 1:
                        height = value;
                        break;
                    default:
                        throw new IndexOutOfRangeException("Index was outside the bounds of the edge array.");

                }
            }
        }

        public double Area {
            get {
                if (IsValid()) {
                    return width * height;
                }
                throw new InvalidGraphException("Graph is invalid.");
            }
        }

        public bool IsValid() {
            return (width > 0) && (height > 0);
        }
    }

    public class Square : Rectangle {
        public Square(double side) : base(side, side) { }
        override public double this[int index] {
            get {
                switch (index) {
                    case 0:
                        return width;
                    default:
                        throw new IndexOutOfRangeException("Index was outside the bounds of the edge array.");
                }
            }
            set {
                switch (index) {
                    case 0:
                        width = height = value;
                        break;
                    default:
                        throw new IndexOutOfRangeException("Index was outside the bounds of the edge array.");
                }
            }
        }
    }

    class Program {
        static void Main(string[] args) {
            Graph rectangle = new Rectangle(2.0, 3.5);
            Graph square = new Square(3.2);
            Graph triangle = new Triangle(3.0, 4.0, 8.0);
            Console.WriteLine("Rectangle(2.0, 3.5)");
            Console.WriteLine("Is Feasible: " + rectangle.IsValid());
            Console.WriteLine("Area: " + rectangle.Area.ToString("N2"));
            Console.WriteLine("Square(3.2)");
            Console.WriteLine("Is Feasible: " + square.IsValid());
            Console.WriteLine("Area: " + square.Area.ToString("N2"));
            Console.WriteLine("Triangle(3.0, 4.0, 8.0)");
            Console.WriteLine("Is Feasible: " + triangle.IsValid());
            triangle[2] = 5.0;
            Console.WriteLine("Triangle(3.0, 4.0, 8.0) -> Triangle(3.0, 4.0, 5.0)");
            Console.WriteLine("Is Feasible: " + triangle.IsValid());
            Console.WriteLine("Area: " + triangle.Area.ToString("N2"));
        }
    }
}
